import { DebugServerConnection } from "../connection/DebugServerConnection";
import { EConnectState } from "../connection/EConnectState";
import { EMessageC2S } from "../../common/EMessageC2S";
import { EMessageS2C } from "../../common/EMessageS2C";
import { EMessageC2C } from "../../common/EMessageC2C";
import { TransPack } from "../../server/framework/common/TransPack";
import { CommonOperateBack } from "../debug_inject/common/CommonOperateBack";
import { Data_Vec3 } from "../debug_inject/common/Data_Vec3";

export class DebuggerManager {

    private static _instance: DebuggerManager;
    public static get instance(): DebuggerManager {
        return this._instance;
    }

    public static CreateInstance() {
        this._instance = new DebuggerManager();
    }

    private _connection: DebugServerConnection;

    public get isReady(): boolean {
        return this._connection.state == EConnectState.Connected;
    }

    private constructor() {
        this._connection = new DebugServerConnection('ws://127.0.0.1:8787');
        this._connection.Connect();
    }

    /**
     * 查询客户端列表
     */
    public QueryClientList() {
        this._connection.Send(EMessageC2S.QueryClientList, null);
    }

    /**
     * 查询obj列表
     */
    public QueryObjList(isForce: boolean) {
        this._SendTransPack(EMessageC2C.QueryObjList, { isForce: isForce });
    }

    /**
     * 查询obj详情
     */
    public QueryObjDetails(objId: number) {
        this._SendTransPack(EMessageC2C.QueryObjDetail, objId);
    }

    /**
     * 查询场景渲图
     * @param objId 
     * @param width 
     * @param height 
     */
    public QuerySceneImg(objId: number, width: number, height: number, isForce: boolean) {
        this._SendTransPack(EMessageC2C.QuerySceneImg, { id: objId, width: width, height: height, isForce: isForce });
    }

    public async SetObjActive(objId: number, active: boolean): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetObjActive, { id: objId, active: active });
    }

    public async SetObjName(objId: number, name: string): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetObjName, { id: objId, name: name });
    }

    public async LogToConsole(objId: number): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.LogToConsole, objId);
    }

    public async SetLocalPos(objId: number, vec3: Data_Vec3): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetLocalPos, { id: objId, pos: vec3 });
    }

    public async SetLocalRot(objId: number, vec3: Data_Vec3): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetLocalRot, { id: objId, rot: vec3 });
    }

    public async SetLocalScale(objId: number, vec3: Data_Vec3): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetLocalScale, { id: objId, scale: vec3 });
    }

    public async SetEnableFog(objId: number, enable: boolean): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetEnableFog, { id: objId, enable: enable });
    }

    public async SetFogColor(objId: number, vec3: Data_Vec3): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetFogColor, { id: objId, color: vec3 });
    }

    public async SetFogStart(objId: number, startDistance: number): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetFogStart, { id: objId, startDistance: startDistance });
    }

    public async SetFogRange(objId: number, fogRange: number): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.SetFogRange, { id: objId, fogRange: fogRange });
    }

    public async SetSceneCameraRot(x: number, y: number) {
        return await this._WaitOperation(EMessageC2C.SetSceneCameraRot, { x: x, y: y });
    }

    public async SetSceneCameraPos(x: number, z: number) {
        return await this._WaitOperation(EMessageC2C.SetSceneCameraPos, { x: x, z: z });
    }

    public async ResetSceneCameraPos(): Promise<boolean> {
        return await this._WaitOperation(EMessageC2C.ResetCameraPos, null);
    }

    private async _WaitOperation(eventId: number, data: any): Promise<boolean> {
        return new Promise((resolve, reject) => {
            this._SendTransPack(eventId, data);
            this._connection.RegistClientMsg(EMessageC2C.CommonOperate_Back, null, (backData: TransPack) => {
                let data = backData.data as CommonOperateBack;
                resolve(data.code != -1);
            }, true);
        });
    }

    private _SendTransPack(realMsgId: number, realMsgData: any = null) {
        if (realMsgData == null) {
            this._connection.Send(EMessageC2S.TransToOther, { type: realMsgId });
        } else {
            this._connection.Send(EMessageC2S.TransToOther, { type: realMsgId, data: realMsgData });
        }
    }

    public async ConnectClient(clientId: number): Promise<boolean> {
        let result = await this.WaitForBack(EMessageC2S.ConnectClient, clientId, EMessageS2C.ConnectClient);
        return result;
    }

    public async WaitForBack(sendId: number, sendData: any, waitId: number): Promise<any> {
        return new Promise((resolve, reject) => {
            this._connection.Send(sendId, sendData);
            this._connection.RegistMsg(waitId, null, (backData: any) => {
                resolve(backData);
            }, true);
        });
    }

    public RegistClientMsg(msgId: number, caller: any, act: Function, once: boolean = false) {
        this._connection.RegistClientMsg(msgId, caller, act, once);
    }

    public UnRegistClientMsg(msgId: number) {
        this._connection.UnRegistClientMsg(msgId);
    }

    public RegistMsg(msgId: number, caller: any, act: Function, once: boolean = false) {
        this._connection.RegistMsg(msgId, caller, act, once);
    }

    public UnRegistMsg(msgId: number) {
        this._connection.UnRegistMsg(msgId);
    }

}